package com.raven.play.stream.test.javadsl.tutorial;

import akka.actor.typed.ActorRef;
import akka.actor.typed.Behavior;
import akka.actor.typed.javadsl.AbstractBehavior;
import akka.actor.typed.javadsl.ActorContext;
import akka.actor.typed.javadsl.Behaviors;
import akka.actor.typed.javadsl.Receive;
import com.raven.play.stream.test.BaseTest;
import org.junit.jupiter.api.Test;

/**
 * FIXME: 2023-12-26 11:39:56 与Actor结合时, 背压怎么处理?
 * 看 Alpakka 的例子, 不是这么用的
 */
public class $15IntegratingWithActors extends BaseTest {

    /**
     * Flow.ask(Actor,...)
     * 元素的处理等待 Actor 的返回
     */
    @Test
    public void test1() {
    }

    /**
     * 如果 Actor 作为 Source, 则不支持背压
     */
    @Test
    public void test2() {
    }

    /**
     * 如果 Actor 作为 Sink, 看到有 Sink.actorRefWithBackpressure() 方法, 可以传 ack
     */
    @Test
    public void test3() {
        // Sink.actorRefWithBackpressure()
    }

    interface Command {
    }

    ;

    record Message<T>(T text, ActorRef<Response> replyTo) implements Command {
    }

    record Response<T>(T text) implements Command {
    }


    class SimpleActor extends AbstractBehavior<Command> {

        private SimpleActor(ActorContext<Command> context) {
            super(context);
        }

        public Behavior<Command> create() {
            return Behaviors.setup(SimpleActor::new);
        }

        @Override
        public Receive<Command> createReceive() {
            return newReceiveBuilder()
                    .onMessage(Message.class, this::OnMsg)
                    .build();
        }

        private Behavior<Command> OnMsg(Message<?> msg) {
            Object text = msg.text;
            ActorRef<Response> replyTo = msg.replyTo;
            if (text instanceof String) {
                log.info("Received a String: {}", text);
                replyTo.tell(new Response<>("%s%s".formatted(text, text)));
            } else if (text instanceof Integer) {
                log.info("Received a Integer: {}", text);
                replyTo.tell(new Response<>((int) text * 2));
            }
            return this;
        }

    }
}
